package test

import (
	"fmt"
	"encoding/json"
	"github.com/liuxd6825/dapr-go-ddd-sdk/applog"
	"github.com/liuxd6825/dapr-go-ddd-sdk/daprclient"
	"github.com/liuxd6825/dapr-go-ddd-sdk/ddd"
	"github.com/liuxd6825/dapr-go-ddd-sdk/ddd/ddd_repository/ddd_mongodb"
	"github.com/liuxd6825/dapr-go-ddd-sdk/restapp"
    "github.com/liuxd6825/dapr-go-ddd-sdk/errors"
	"github.com/liuxu6825/dapr-go-ddd-example/pkg/query-service/infrastructure/db/dao/mongo_dao"
	"github.com/liuxu6825/dapr-go-ddd-example/pkg/query-service/infrastructure/db/dao/mysql_dao"
	"github.com/liuxu6825/dapr-go-ddd-example/pkg/query-service/infrastructure/db/dao/neo4j_dao"
	"github.com/neo4j/neo4j-go-driver/v4/neo4j"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
)

const (
	EnvName  = "dev"
	TenantId = "test"
)

//
// InitQuery
// @Description: 初始化QueryService测试环境
//
func InitQuery() {
    // 加载配置文件
	config, err := restapp.NewConfigByFile("${search}/config/query-config.yaml")
	if err != nil {
		panic(err)
	}

    // 读取指定环境下的配置信息
	env, err := config.GetEnvConfig(EnvName)
	if err != nil {
		panic(err)
	}

	// 创建dapr客户端
	daprClient, err := daprclient.NewDaprDddClient(env.Dapr.GetHost(), env.Dapr.GetHttpPort(), env.Dapr.GetGrpcPort())
	if err != nil {
		panic(err)
	}
    // 注册dapr客户端
	daprclient.SetDaprDddClient(daprClient)

    // 初始化ddd
	ddd.Init(env.App.AppId)
	applog.Init(daprClient, env.App.AppId, applog.INFO)

    // 初始化数据库
    initMongo(env.Mongo["default"])
    initNeo4j(env.Neo4j["default"])
    initMysql(env.Mysql["default"])
}


//
// GetResponseData
// @Description: 获取http响应数据
// @param t  *testing.T 测试对象
// @param resp *httpexpect.Response Http响应对象
// @param data 数据指针
// @return error 错误
//
func GetResponseData(t *testing.T, resp *httpexpect.Response, data interface{}) error {
	raw := resp.Raw()
	switch raw.StatusCode {
	case httptest.StatusOK:
		break
	case httptest.StatusNotFound:
		return errors.New(fmt.Sprintf("%v", raw.Status))
	default:
		return errors.New(fmt.Sprintf("%v, %v ", raw.Status, resp.Body().Raw()))
	}

	body := resp.Body()
	bytes := []byte(body.Raw())
	t.Log(body.Raw())
	if err := json.Unmarshal(bytes, data); err != nil {
		return err
	}
	return nil
}

func initMongo(dbConfig *restapp.MongoConfig) {
	config := &ddd_mongodb.Config{
		Host:         dbConfig.Host,
		UserName:     dbConfig.UserName,
		Password:     dbConfig.Password,
		ReplicaSet:   dbConfig.ReplicaSet,
		DatabaseName: dbConfig.Database,
		MaxPoolSize:  dbConfig.MaxPoolSize,
	}
	db, err := ddd_mongodb.NewMongoDB(config)
	if err != nil {
		panic(err)
	}
	mongo_dao.SetDB(db)
}

func initNeo4j(dbConfig *restapp.Neo4jConfig) {
	cfg := func(config *neo4j.Config) {
		config.MaxConnectionPoolSize = 10
	}
	neo4jUil := fmt.Sprintf("bolt://%v:%v", dbConfig.Host, dbConfig.Port)
	configures := []func(*neo4j.Config){cfg}
	driver, err := neo4j.NewDriver(neo4jUil, neo4j.BasicAuth(dbConfig.UserName, dbConfig.Password, ""), configures...)
	if err != nil {
		panic(err)
	}
	neo4j_dao.SetDB(driver)
}

func initMysql(dbConfig *restapp.MySqlConfig) {
	dsn := fmt.Sprintf("%v:%v@tcp(%v:%v)/%v?charset=utf8&parseTime=True&loc=Local", dbConfig.UserName, dbConfig.Password, dbConfig.Host, dbConfig.Port, dbConfig.Database)

	db, err := gorm.Open(mysql.New(mysql.Config{
		DSN:                       dsn,   // DSN data source name
		DefaultStringSize:         256,   // string 类型字段的默认长度
		DisableDatetimePrecision:  true,  // 禁用 datetime 精度，MySQL 5.6 之前的数据库不支持
		DontSupportRenameIndex:    true,  // 重命名索引时采用删除并新建的方式，MySQL 5.7 之前的数据库和 MariaDB 不支持重命名索引
		DontSupportRenameColumn:   true,  // 用 `change` 重命名列，MySQL 8 之前的数据库和 MariaDB 不支持重命名列
		SkipInitializeWithVersion: false, // 根据当前 MySQL 版本自动配置
	}), &gorm.Config{Logger: logger.Default.LogMode(logger.Info)})

	if err != nil {
		panic(err)
	}

	mysql_dao.SetDB(db)
}


// PrintJson 以JSON格式打印
func PrintJson(t *testing.T, title string, data interface{}) error {
	bs, err := json.Marshal(data)
	if err != nil {
		return err
	}
	t.Log(title)
	t.Log(string(bs))
	return nil
}
